<template>
  <main-card-admin title="标签管理" :show-screen-space="false" :loading="globalLoading">
    <a-row class="page mt-30">
      <a-col class="tabs" style="width: 188px">
        <div
          v-for="tab in tabs"
          :key="tab.key"
          class="cursor-pointer tab"
          :class="[tab.key === currentTab && 'tab--active']"
          @click="onTabChange(tab)"
        >
          {{ tab.name }}
        </div>
      </a-col>
      <a-col>
        <div class="table">
          <a-row class="table__header" :align="'middle'">
            <a-col class="title" />
            <a-col class="title"> 排序 </a-col>
            <a-col class="title" flex="1"> 标签 </a-col>
          </a-row>
          <div class="table__body">
            <draggable v-model="tagList" group="people" item-key="id" @start="startDraggable" @end="moveTag">
              <template #item="{ element: tag, index }">
                <a-row class="list-item" :align="'middle'">
                  <a-col class="move-icon">
                    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none">
                      <path
                        fill-rule="evenodd"
                        clip-rule="evenodd"
                        d="M6.125 15.5C5.50625 15.5 5 14.9937 5 14.375C5 13.7563 5.50625 13.25 6.125 13.25C6.74375 13.25 7.25 13.7563 7.25 14.375C7.25 14.9937 6.74375 15.5 6.125 15.5ZM6.125 4.25C5.50625 4.25 5 3.74375 5 3.125C5 2.50625 5.50625 2 6.125 2C6.74375 2 7.25 2.50625 7.25 3.125C7.25 3.74375 6.74375 4.25 6.125 4.25ZM6.125 9.875C5.50625 9.875 5 9.36875 5 8.75C5 8.13125 5.50625 7.625 6.125 7.625C6.74375 7.625 7.25 8.13125 7.25 8.75C7.25 9.36875 6.74375 9.875 6.125 9.875ZM12.125 15.5C11.5062 15.5 11 14.9937 11 14.375C11 13.7563 11.5062 13.25 12.125 13.25C12.7438 13.25 13.25 13.7563 13.25 14.375C13.25 14.9937 12.7438 15.5 12.125 15.5ZM12.125 4.25C11.5062 4.25 11 3.74375 11 3.125C11 2.50625 11.5062 2 12.125 2C12.7438 2 13.25 2.50625 13.25 3.125C13.25 3.74375 12.7438 4.25 12.125 4.25ZM12.125 9.875C11.5062 9.875 11 9.36875 11 8.75C11 8.13125 11.5062 7.625 12.125 7.625C12.7438 7.625 13.25 8.13125 13.25 8.75C13.25 9.36875 12.7438 9.875 12.125 9.875Z"
                        fill="#191930"
                        fill-opacity="0.75"
                      />
                    </svg>
                  </a-col>
                  <a-col class="index">{{ index + 1 }}</a-col>
                  <a-col class="name" flex="1"> {{ tag.v }}</a-col>
                  <a-col class="tools">
                    <a-tooltip placement="top">
                      <template #title>
                        <span>编辑</span>
                      </template>
                      <a-button type="text" class="mr-20 icon-only-btn" @click="openEditModal(tag)">
                        <i class="iconfont icon-edit-line" style="font-size: 18px"></i>
                      </a-button>
                    </a-tooltip>
                    <a-tooltip placement="top">
                      <template #title>
                        <span>删除</span>
                      </template>
                      <a-button type="text" class="icon-only-btn" @click="judgeIsCanDelete(tag)">
                        <i class="iconfont icon-delete-bin-line" style="font-size: 18px"></i>
                      </a-button>
                    </a-tooltip>
                  </a-col>
                </a-row>
              </template>
            </draggable>
          </div>
          <a-row class="table__footer" :align="'middle'" justify="space-between">
            <a-col>
              <a-input
                v-model:value="addInputValue"
                v-trim
                class="h-38"
                style="width: 672px"
                :maxlength="20"
                :placeholder="`请输入${currentTabName}`"
              />
            </a-col>
            <a-col>
              <a-button type="primary" style="width: 132px" @click="addTag">添加</a-button>
            </a-col>
          </a-row>
        </div>
      </a-col>
      <a-col flex="3" />
    </a-row>
  </main-card-admin>

  <a-modal
    v-model:open="isShowEditModal"
    title="修改标签"
    style="width: 416px"
    centered
    :ok-button-props="{ loading: isEditTagLoading }"
    @ok="editTag"
    @cancel="resetForm"
  >
    <a-form ref="formRef" :model="formState" name="basic" layout="vertical" class="my-a-form" :rules="rules">
      <div class="on-line-two-item">
        <a-form-item label="" name="tagName">
          <a-input v-model:value="formState.tagName" v-trim style="width: 352px" :maxlength="20" :placeholder="`请输入${currentTabName}`" />
        </a-form-item>
      </div>
    </a-form>
  </a-modal>
  <a-modal v-model:open="isShowDeleteFailModal" title="删除失败" width="420px" centered :after-close="closeDeleteFailModal">
    <div class="delete-fail-tips">
      <i class="iconfont icon-close-circle-fill mr-8"></i>
      此标签为以下{{ typeName }}的唯一标签，暂不支持删除
    </div>
    <div class="delete-fail-list">
      <div v-for="(item, index) in canNotDeleteDataList" :key="index" class="delete-fail-item">
        <div class="elliptical-1" :title="item">
          {{ item }}
        </div>
      </div>
    </div>
    <template #footer> </template>
  </a-modal>

  <delete-confirm-dialog
    v-model:show="isDeleteDialogShow"
    :msg="deleteConfirmMag"
    label="请输入名称"
    :confirm-name="deleteConfigName"
    :loading="confirmLoading"
    @ok="onOkDeleteTag"
  />
</template>

<script lang="ts" setup>
  import type { FormInstance } from 'ant-design-vue'
  import { message } from 'ant-design-vue'
  import type { Rule } from 'ant-design-vue/es/form'
  import { nextTick, onMounted, ref, watch } from 'vue'
  import { computed } from 'vue'
  import { useRequest } from 'vue-request'
  import Draggable from 'vuedraggable'

  import { tagManageApi } from '@/services/api'

  import { FormState, Tab, TabKey, Tag } from './types'

  const tagList = ref<Tag[]>([])
  let container: Element

  const globalLoading = computed(
    () =>
      isGetTagListLoading.value ||
      isAddTagLoading.value ||
      isGetNumLoading.value ||
      isSortTagLoading.value ||
      isDelTagLoading.value ||
      isGetCanNotDeleteLoading.value
  )

  const { runAsync: runGetTagList, loading: isGetTagListLoading } = useRequest<ResponseData<Tag[]>>(tagManageApi.list, {
    onSuccess: res => (tagList.value = res.data)
  })
  async function getTagList() {
    runGetTagList({ type: currentTab.value })
  }
  /* 标签类型切换逻辑----------------------------------------------------------- */
  const tabs = ref<Tab[]>([
    {
      name: '课程分类',
      key: 'course_category',
      delApiType: 'course-label'
    },
    {
      name: '课程级别',
      key: 'course_level',
      delApiType: 'course-label'
    },
    {
      name: '案例类别',
      key: 'proj',
      delApiType: 'proj-label'
    },
    {
      name: '模型标签',
      key: 'common_model',
      delApiType: 'commom-model-label'
    },
    // {
    //   name: '算法类型',
    //   key: 'algorithm_type',
    //   delApiType: 'algorithm-label'
    // },
    {
      name: '打榜类型',
      key: 'rank_type',
      delApiType: 'rank-type'
    },
    {
      name: '服务类型',
      key: 'type_tag',
      delApiType: 'service-label'
    },
    {
      name: '服务标签',
      key: 'special_tag',
      delApiType: 'service-label'
    }
  ])

  const currentTab = ref<TabKey>('course_category')
  const currentTabName = computed(() => tabs.value.find(item => item.key === currentTab.value)?.name)
  const currentTabApiType = computed(() => tabs.value.find(item => item.key === currentTab.value)?.delApiType)

  watch(currentTab, getTagList, { immediate: true })

  const onTabChange = (tab: any) => {
    currentTab.value = tab.key
    addInputValue.value = ''
  }

  /* 新增标签逻辑----------------------------------------------------------- */
  const addInputValue = ref('')
  // useRequest
  const { runAsync: runAddTag, loading: isAddTagLoading } = useRequest(tagManageApi.add)
  const addTag = async () => {
    if (!addInputValue.value) {
      message.warn('请输入标签名称')
      return
    }

    await runAddTag({
      type: currentTab.value,
      v: addInputValue.value
    })
    message.success(`添加标签成功`)
    addInputValue.value = ''
    await getTagList()
    nextTick(() => {
      container.scrollTop = container.scrollHeight - container.clientHeight
    })
  }
  /* 编辑标签逻辑----------------------------------------------------------- */
  const isShowEditModal = ref(false)
  const currentTag = ref<Tag>()
  const formRef = ref<FormInstance>()
  const formState = ref<FormState>({
    tagName: ''
  })
  const { runAsync: runUpdateTag, loading: isEditTagLoading } = useRequest(tagManageApi.update)

  const validatorTagName = (rule: Rule, value: string) => {
    if (value === '') {
      return Promise.reject(`请输入${currentTabName.value}`)
    }
    return Promise.resolve()
  }
  const rules: Record<string, Rule[]> = {
    tagName: [{ required: true, validator: validatorTagName }]
  }

  const openEditModal = (tag: Tag) => {
    currentTag.value = tag
    formState.value.tagName = tag.v
    isShowEditModal.value = true
  }
  const closeEditModal = () => {
    isShowEditModal.value = false
  }

  const editTag = async () => {
    await formRef.value?.validateFields()
    await runUpdateTag({ id: currentTag.value!.id, v: formState.value.tagName })
    message.success(`编辑成功`)
    closeEditModal()
    getTagList()
  }

  const resetForm = () => {
    isShowEditModal.value = false

    formState.value = {
      tagName: ''
    }
    formRef.value?.resetFields()
  }
  /* 移动标签逻辑----------------------------------------------------------- */
  //useRequest
  const { runAsync: runSortTag, loading: isSortTagLoading } = useRequest(tagManageApi.sort)
  const drag = ref(false)
  const startDraggable = () => {
    drag.value = true
  }
  const moveTag = () => {
    drag.value = false
    const ids = tagList.value.map(it => it.id)
    runSortTag({ ids })
  }

  /* 删除标签逻辑----------------------------------------------------------- */
  const relevanceNum = ref(0) //关联数量
  const typeName = ref('') //关联类型
  const isGetNumLoading = computed(() => isGetBindNumLoading.value)

  const isShowDeleteFailModal = ref(false) // 显示不可删除弹窗
  const canNotDeleteDataList = ref<string[]>([]) // 不可删除的数据列表
  const isGetCanNotDeleteLoading = computed(() => isGetCanNotDeleteItemLoading.value)

  // 查询不可删除数据的useRequest
  type DataRes = ResponseData<string[]>

  const { runAsync: runGetCanNotDeleteItem, loading: isGetCanNotDeleteItemLoading } = useRequest<DataRes>(tagManageApi.getCanNotDeleteNum, {
    onSuccess: res => (canNotDeleteDataList.value = res.data)
  })

  //查询关联数量的useRequest
  type NumberRes = ResponseData<number>
  const { runAsync: runGetBindNum, loading: isGetBindNumLoading } = useRequest<NumberRes>(tagManageApi.bindNum, {
    onSuccess: res => (relevanceNum.value = res.data)
  })

  //删除的useRequest
  const { runAsync: runDeleteTag, loading: isDelTagLoading } = useRequest(tagManageApi.del, {
    onSuccess: () => {
      message.success(`删除成功`)
      getTagList()
    }
  })

  // 判断是否可以删除
  const judgeIsCanDelete = async (tag: any) => {
    const params = {
      labelId: tag.id
    }
    const urlParams = {
      type: currentTabApiType.value
    }
    await runGetCanNotDeleteItem(params, { urlParams })
    switch (currentTab.value) {
      case 'course_category':
      case 'course_level':
        typeName.value = '课程'
        break
      case 'proj':
        typeName.value = '案例'
        break
      case 'common_model':
        typeName.value = '模型'
        break
      case 'algorithm_type':
        typeName.value = '算法'
        break
      case 'rank_type':
        typeName.value = '打榜'
        break
      case 'type_tag':
      case 'special_tag':
        typeName.value = '服务'
        break
      default:
        break
    }
    // 如果有不可删除的数据，弹窗提示
    if (canNotDeleteDataList.value.length) {
      openDeleteFailModal()
      return
    }
    openDeleteTagModal(tag)
  }

  const openDeleteFailModal = async () => {
    isShowDeleteFailModal.value = true
  }
  const closeDeleteFailModal = () => {
    isShowDeleteFailModal.value = false
  }

  const isDeleteDialogShow = ref(false)
  const deleteConfirmMag = ref('')
  const deleteConfigName = ref('')
  const confirmLoading = ref(false)
  const deleteID = ref<string>('')
  const onOkDeleteTag = async () => {
    confirmLoading.value = true
    const urlParams = {
      id: deleteID.value
    }
    try {
      await runDeleteTag({}, { urlParams })
      isDeleteDialogShow.value = false
    } finally {
      confirmLoading.value = false
    }
  }

  // 打开删除弹窗
  const openDeleteTagModal = async (tag: any) => {
    deleteID.value = tag.id
    deleteConfigName.value = tag.v
    relevanceNum.value = 0
    const urlParams = {
      id: tag.id,
      type: currentTabApiType.value
    }
    await runGetBindNum({}, { urlParams })
    deleteConfirmMag.value = `已有${relevanceNum.value}个${typeName.value}使用此标签，请确认是否删除`
    isDeleteDialogShow.value = true
  }

  /* ----------------------------------------------------------- */

  onMounted(() => {
    container = document.querySelector('.table__body')!
  })
</script>

<style lang="less" scoped>
  @import '@/styles/mixins.less';

  .my-a-form {
    :deep(.ant-form-item) {
      margin-bottom: 0;
    }
  }

  .page {
    .tabs {
      padding: 24px;
      margin-right: 20px;
      width: 140px;
      background: #fafafa;
      border-radius: 10px;

      .tab {
        width: 100%;
        height: 44px;
        border-radius: 6px;
        .text-color-3();
        .fc();
        .font18b();

        &--active {
          color: @text01;
          background-color: #e1e1e1;
        }

        & + .tab {
          margin-top: 24px;
        }
      }
    }

    .table {
      width: 900px;
      border: 1px solid @border1;
      border-radius: 6px;

      .table__header {
        height: 56px;
        background: #fafafa;
        border-radius: 10px;
        border-bottom-left-radius: none;
        border-bottom-right-radius: none;

        .title {
          .fc();

          justify-content: flex-start;
          .text-color-3();
        }

        .title:nth-of-type(1) {
          width: 56px;
        }

        .title:nth-of-type(2) {
          padding-left: 16px;
          width: 110px;
        }

        .title:nth-of-type(3) {
          justify-content: flex-start;
          padding-left: 16px;
        }
      }

      .table__body {
        overflow-y: auto;
        height: 566px;
        border-top: 1px solid @border1;
        border-bottom: 1px solid @border1;

        .list-item {
          display: flex;
          height: 56px;
          color: #000;
          border-bottom: 1px solid @border1;
          cursor: move;

          .ant-col {
            .fc();

            justify-content: flex-start;
            padding-left: 16px;
          }

          .move-icon {
            width: 56px;
            height: 56px;
            visibility: hidden;

            .img {
              width: 18px;
              height: 18px;
            }
          }

          .index {
            width: 110px;
          }

          .tools {
            // visibility: hidden;
            display: none;
            justify-content: center;
            width: 154px;
            .font16();

            color: @text02;
          }

          &.not {
            cursor: default;
          }

          &:hover {
            background-color: rgba(247, 247, 247);

            .move-icon {
              visibility: visible;
            }

            .tools {
              display: flex;
              visibility: visible;
            }
          }
        }
      }

      .table__footer {
        padding: 0 40px;
        height: 86px;
      }
    }
  }

  .delete-fail-tips {
    display: flex;
    align-items: center;
    font-size: 14px;
    color: @text01;

    .iconfont {
      font-size: 24px;
      color: @danger;
    }
  }

  .delete-fail-list {
    overflow: hidden auto;
    margin-top: 24px;
    max-height: 500px;

    .delete-fail-item {
      display: flex;
      align-items: center;
      padding: 12px 16px;
      width: 352px;
      height: 56px;
      border-bottom: 1px solid #e8e8eb;

      & > div {
        width: 100%;
      }
    }

    & > div:nth-of-type(2n + 1) {
      background-color: #fafafa;
    }
  }
</style>
